
/* <<< COPYRIGHT START >>>
 * Copyright 2006-Present OxygenSoftwareLibrary.com
 * Licensed under the GNU Lesser General Public License.
 * http://www.gnu.org/licenses/lgpl.html
 * 
 * @author: Ugorji Dick-Nwoke
 * <<< COPYRIGHT END >>>
 */

package oxygen.tool.wlevs;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.management.MBeanServer;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.QueryExp;

import oxygen.tool.facade.trees.JMXFacadeTreeModel;
import oxygen.tool.facade.trees.JMXUtils;

/**
 * applications (App Name --> Stage Name --> Metric Name)
   /ugorji/
   /ugorji/helloWorldAdapter
   /ugorji/helloWorldAdapter/metric.1.1.20

*/
public class WLEvSApplicationFacadeTreeModel extends JMXFacadeTreeModel {
  private static String domain = "com.bea.wlevs";
  private static List AppNameType = Arrays.asList(new String[]{"Name", "Type", "Application"});
  
  public WLEvSApplicationFacadeTreeModel(MBeanServerConnection mbs0, String name0) throws Exception {
    super(mbs0, name0);
  }
  
  public String getSeparator() {
    return "/";
  }
  
  public Object[] getChildren(Object parent) {
    try {
      ObjectName oname = (ObjectName)parent;
      Object[] kids = new Object[0];
      if(oname == null) {
        ObjectName onamepatt = new ObjectName(domain + ":Type=Application,*");
        Set names = JMXUtils.getAllRegistered(mbs, onamepatt, new MyQueryExp(2));
        kids = names.toArray();
      } else {
        //Name Type
        List l = JMXUtils.getKeys(oname);
        int lsize = l.size();
        if(lsize == 2) { //Application (Name Type)
          kids = (ObjectName[])mbs.getAttribute(oname, "StageMBeans");
        } else if(lsize == 3) { //Stage (Name Type Application)
          ObjectName onamepatt = new ObjectName(domain + ":Type=StageMonitoringMetricRuntime" + 
              ",Application=" + oname.getKeyProperty("Application") + 
              "," + oname.getKeyProperty("Type") + "=" + oname.getKeyProperty("Name") + 
          ",*");
          Set names = JMXUtils.getAllRegistered(mbs, onamepatt, new MyQueryExp(4));
          kids = names.toArray();
        } 
      }
      return kids;
    } catch(Exception exc) {
      throw new RuntimeException(exc);
    }
  }
  
  public Object getParent(Object child) throws Exception {
    ObjectName oname = (ObjectName)child;
    ObjectName parent = null;
    if(oname != null) {
      List l = JMXUtils.getKeys(oname);
      int lsize = l.size();
      if(lsize == 3) {
        ObjectName onamepatt = new ObjectName(domain + ":Type=Application,Name=" + oname.getKeyProperty("Application") + ",*");
        parent = JMXUtils.checkRegistered(mbs, onamepatt, new MyQueryExp(2));
      } else if(lsize == 4) { //Metric (Name Type Application $stageType
        String stageType = getStageType(l);
        ObjectName onamepatt = new ObjectName(domain + ":Application=" + oname.getKeyProperty("Application") + 
                                              ",Type=" + stageType + 
                                              ",Name=" + oname.getKeyProperty(stageType) + 
                                              ",*");
        parent = JMXUtils.checkRegistered(mbs, onamepatt, new MyQueryExp(3));
      }
    }
    return parent;
  }
  
  public Object getChild(Object parent, String pathname) throws Exception {
    Object[] onames = getChildren(parent);
    for(int i = 0; i < onames.length; i++) {
      ObjectName oname = (ObjectName)onames[i];
      if(pathname.equals(oname.getKeyProperty("Name"))) {
        return oname;
      }
    }
    return null;
  }
  
  public String toPathName(Object child) throws Exception {
    ObjectName oname = (ObjectName)child;
    return (oname == null ? (null) : oname.getKeyProperty("Name"));
  }

  private String getStageType(List l) {
    for(Iterator itr = l.iterator(); itr.hasNext(); ) {
      String s = (String)itr.next();
      if(!(AppNameType.contains(s))) {
        return s;
      }
    }
    return null;
  }
  
  private static class MyQueryExp implements QueryExp {
    private int numKeys = 2;
    public MyQueryExp(int numKeys0) {
      numKeys = numKeys0;
    }
    
    public boolean apply(ObjectName oname) {
      List l = JMXUtils.getKeys(oname);
      return (l.size() == numKeys && l.contains("Type") && l.contains("Name"));
    }
    public void setMBeanServer(MBeanServer mbs) { }
  }

  
}
